package com.cipri.battle.ui
{
	import com.cipri.battle.config.Settings;
    import com.cipri.battle.events.BoxHitEvent;
    import com.cipri.battle.events.GameEvent;
    import com.cipri.battle.events.ShapeEvent;
    import flash.events.MouseEvent;
    import flash.geom.Point;
	
	import flash.display.Sprite;

	public class Table extends Sprite
	{
		private var _size:uint;
        private var _boxes:Array = new Array();
		
		public function Table()
		{
			_size = Settings.TABLE_SIZE;
			
			drawTable();
		}
		
        public function placeShape(shape:Shape):Boolean 
        {
            for (var i:uint = 0; i < _size; i++) 
			{
				for (var j:uint = 0; j < _size; j++) 
				{
                    if (Box(_boxes[i][j]).hitTestPoint(shape.getTopLeftCenter().x, shape.getTopLeftCenter().y))
                    {
                        if (!isOkToPosition(shape, i, j)) 
                        {
                            shape.resetPosition();
                            return false;
                        }
                        else 
                        {
                            shape.disableMouseActions();
                            return true;    
                        }
                    }
                }
            }
            shape.resetPosition();
            return false;
        }
        
        public function startGame():void 
        {
            for (var i:uint = 0; i < _size; i++) 
			{
				for (var j:uint = 0; j < _size; j++) 
				{
                    _boxes[i][j].startGame();
                    _boxes[i][j].addEventListener(BoxHitEvent.HIT, onBoxHit);
                }
            }
        }
        
        private function onBoxHit(event:BoxHitEvent):void 
        {
            if (event.oldValue != 0) 
            {
                var isShapeDown:Boolean = true;
                var isGameOver:Boolean = true;
                
                for (var i:uint = 0; i < _size; i++) 
                {
                    for (var j:uint = 0; j < _size; j++) 
                    {
                        if (_boxes[i][j].value > 0) 
                        {
                            isGameOver = false;
                        }
                        if (_boxes[i][j].value == event.oldValue) 
                        {
                            //there is still a bit left of this shape type
                            isShapeDown = false;
                            break;
                        }
                    }
                }
                
                dispatchEvent(new GameEvent(GameEvent.SUCCESSFUL_HIT));
                
                if (isShapeDown) 
                {
                    dispatchEvent(new GameEvent(GameEvent.SHAPE_DOWN, event.oldValue));
                }
                
                if (isGameOver) 
                {
                    dispatchEvent(new GameEvent(GameEvent.GAME_OVER));
                }
            }
            else 
            {
                dispatchEvent(new GameEvent(GameEvent.MISSED_HIT));
            }
        }
        
        private function isOkToPosition(shape:Shape, line:uint, col:uint):Boolean
        {
            var def:Array = shape.definition;
            var newValues:Array = getValues();
            
            for (var i:uint = 0; i < def.length; i++) 
			{
                if (def[i].length + col > _size) 
                {
                    //the shape is too wide and its leaving the table
                    return false;
                }
				for (var j:uint = 0; j < def[i].length; j++) 
				{
                    if (def[i][j] > 0) 
                    {
                        //if the shape is defined in i,j
                        if (_boxes[i + line][j + col].value != 0) 
                        {
                            //if the box on the table is already taken
                            return false;
                        }
                    }
                    newValues[i + line][j + col] = def[i][j];
                }
            }
            
            setValues(newValues);
            shape.x = col * Settings.TABLE_CELL_SIZE + Settings.TABLE_X;
            shape.y = line * Settings.TABLE_CELL_SIZE + Settings.TABLE_Y;
            
            return true;
        }
        
		private function drawTable():void 
		{
			var box:Box;
			for (var i:uint = 0; i < _size; i++) 
			{
                _boxes[i] = new Array();
				for (var j:uint = 0; j < _size; j++) 
				{
					box = new Box(0, Settings.TABLE_BACKGROUND_COLOR);
					box.x = j * Settings.TABLE_CELL_SIZE;
					box.y = i * Settings.TABLE_CELL_SIZE;
                    _boxes[i].push(box);
					addChild(box);
				}
			}
		}
        
        private function getValues():Array 
        {
            var values:Array = new Array();
            for (var i:uint = 0; i < _size; i++) 
			{
                values[i] = new Array();
				for (var j:uint = 0; j < _size; j++) 
				{
                    values[i].push(Box(_boxes[i][j]).value);
                }
            }
            return values;
        }
        
        private function setValues(values:Array):void
        {
            for (var i:uint = 0; i < _size; i++) 
			{
				for (var j:uint = 0; j < _size; j++) 
				{
                    _boxes[i][j].value = values[i][j];
                }
            }
        }
	}
}